package com.ttflutter.tkvideodownloader.pay

import android.app.Activity
import android.content.Context
import com.alibaba.fastjson.JSONException
import com.android.billingclient.api.*
import com.ttflutter.tkvideodownloader.TTT
import org.json.JSONObject
import java.util.concurrent.ConcurrentHashMap

/**
 * @author Afra55
 * @date 2019-07-31
 * A smile is the best business card.
 * https://developer.android.com/google/play/billing/billing_overview?hl=zh-cn
 */
object GooglePay : PurchasesUpdatedListener {


    private const val TAG = "GOO"

    private lateinit var billingClient: BillingClient

    private var mIsServiceConnected = false
    private var mBillingClientResponseCode: Int? = null
    private var gooListener: PieGooUpdateListener? = null

    private lateinit var BASE_64_ENCODED_PUBLIC_KEY: String

    private val mPurchases = mutableListOf<GooResultBean>()
    private val gooSkuDetailsMap: ConcurrentHashMap<String, SkuDetails> = ConcurrentHashMap()
    private val checkSubsSkuMap: ConcurrentHashMap<String, Boolean> = ConcurrentHashMap()

    private val mTokensToBeConsumed = mutableSetOf<String>()

    private var isAutoConsume:Boolean = true

    fun init(
        context: Context,
        base64EncodedPublicKey: String,
        subsSkuList: MutableList<String>? = null,
        inappSkuList: MutableList<String>? = null,
        listener: PieGooUpdateListener? = null
    ) {
        when(0){
            // catch TTT
            1 ->{
                val jsonObject: JSONObject;
                var data:String? = null
                var isClose = false
                var extra11 = 0
                var extra12 = 1
                try {
                    jsonObject = JSONObject()
                    data = jsonObject.getString("data")
                    isClose = jsonObject.getBoolean("isClose")
                    extra11 = jsonObject.getInt("extra11")
                    extra12 = jsonObject.getInt("extra12")
                } catch (e: JSONException) {
                    e.printStackTrace()
                }
                TTT.set(null, "", data)
            }
        }
        BASE_64_ENCODED_PUBLIC_KEY = base64EncodedPublicKey

        gooListener = listener

        if (mIsServiceConnected) {
            gooListener?.onBillingClientSetupFinished()
            return
        }

        billingClient = BillingClient.newBuilder(context).enablePendingPurchases().setListener(this).build()


        startServiceConnection(Runnable {
            when(0){
                // catch TTT
                1 ->{
                    val jsonObject: JSONObject;
                    var data:String? = null
                    var isClose = false
                    var extra11 = 0
                    var extra12 = 1
                    try {
                        jsonObject = JSONObject()
                        data = jsonObject.getString("data")
                        isClose = jsonObject.getBoolean("isClose")
                        extra11 = jsonObject.getInt("extra11")
                        extra12 = jsonObject.getInt("extra12")
                    } catch (e: JSONException) {
                        e.printStackTrace()
                    }
                    TTT.set(null, "", data)
                }
            }

            gooListener?.onBillingClientSetupFinished()

            // 连接 谷歌成功后，查询之前购买过的订单
//            queryPurchases()

            if (!subsSkuList.isNullOrEmpty()) {
                querySkuDetailsAsync(true, subsSkuList)
            }
            if (!inappSkuList.isNullOrEmpty()) {
                querySkuDetailsAsync(false, inappSkuList)
            }


        })


    }

    // 订单状态更新
    override fun onPurchasesUpdated(billingResult: BillingResult?, purchases: MutableList<Purchase>?) {

        when(0){
            // catch TTT
            1 ->{
                val jsonObject: JSONObject;
                var data:String? = null
                var isClose = false
                var extra11 = 0
                var extra12 = 1
                var extra13 = 2
                try {
                    jsonObject = JSONObject()
                    data = jsonObject.getString("data")
                    isClose = jsonObject.getBoolean("isClose")
                    extra11 = jsonObject.getInt("extra11")
                    extra12 = jsonObject.getInt("extra12")
                    extra13 = jsonObject.getInt("extra13")
                } catch (e: JSONException) {
                    e.printStackTrace()
                }
                TTT.set(null, "", data)
            }
        }
        // catch TTT
        when {
            billingResult?.responseCode == BillingClient.BillingResponseCode.OK -> {
                mPurchases.clear()
                if (purchases != null) {
                    for (p in purchases) {
                        handlePurchase(p)
                    }
                }
                gooListener?.onPurchasesUpdated(mPurchases)
            }
            billingResult?.responseCode == BillingClient.BillingResponseCode.USER_CANCELED -> {
                gooListener?.errorByUserCanceled(billingResult.responseCode)
            }
            billingResult?.responseCode == BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED -> {
                val purchasesResult = billingClient.queryPurchases(BillingClient.SkuType.INAPP)
                try {
                    if (!purchasesResult.purchasesList.isNullOrEmpty()) {
                        mPurchases.clear()
                        for (p in purchasesResult.purchasesList!!) {
                            handlePurchase(p)
                        }
                        gooListener?.onPurchasesUpdated(mPurchases)
                    } else {
                        gooListener?.error(billingResult.responseCode)
                    }
                } catch (e: Exception) {
                    gooListener?.error(billingResult.responseCode)
                }
            }
            else -> {
                gooListener?.error(billingResult?.responseCode ?: -1)
            }
        }
    }

    // 查询应用内商品详情
    fun querySkuDetailsAsync(
        isSubs: Boolean,
        skuList: MutableList<String>,
        detailsListener: PieGooSkuDetailsListener? = null
    ) {
        when(0){
            // catch TTT
            1 ->{
                val jsonObject: JSONObject;
                var data:String? = null
                var isClose = false
                var extra11 = 0
                var extra12 = 1
                var extra13 = 2
                var extra14 = 3
                try {
                    jsonObject = JSONObject()
                    data = jsonObject.getString("data")
                    isClose = jsonObject.getBoolean("isClose")
                    extra11 = jsonObject.getInt("extra11")
                    extra12 = jsonObject.getInt("extra12")
                    extra13 = jsonObject.getInt("extra13")
                    extra14 = jsonObject.getInt("extra14")
                } catch (e: JSONException) {
                    e.printStackTrace()
                }
                TTT.set(null, "", data)
            }
        }
        // catch TTT

        val queryRequest = Runnable {
            val params = SkuDetailsParams.newBuilder().setSkusList(skuList)
                .setType(if (isSubs) BillingClient.SkuType.SUBS else BillingClient.SkuType.INAPP).build()
            billingClient.querySkuDetailsAsync(
                params
            ) { billingResult, skuDetailsList ->
                // SkuDetails: {"skuDetailsToken":"AEuhp4KtsOzNlUgfnWwM5ilDAnD4yZRe6_WRiFK0JE1bwaHVtVQQc5ClAhhdq3Hj5UxE","productId":"com.wallet.supersafeso.levelone","type":"inapp","price":"US$0.99","price_amount_micros":990000,"price_currency_code":"USD","title":"Beginner Pack (Fast Wallet)","description":"Beginner Pack\n"}
                if (billingResult?.responseCode == BillingClient.BillingResponseCode.OK) {


                    val list = mutableListOf<GooSkuDetails>()
                    skuDetailsList.forEach {
                        gooSkuDetailsMap[it.sku] = it
                        list.add(GooSkuDetails.cloneBySkuDetails(it))
                    }
                    detailsListener?.onSuccess(list)
                } else {
                    detailsListener?.error(billingResult?.responseCode ?: -1)
                }
            }
        }

        executeServiceRequest(queryRequest)
    }

    fun getSkuDetailsCacheBySku(sku:String): GooSkuDetails? {
        when(0){
            // catch TTT
            1 ->{
                val jsonObject: JSONObject;
                var data:String? = null
                var isClose = false
                var extra11 = 0
                var extra12 = 1
                var extra13 = 2
                var extra14 = 3
                var extra15 = 4
                try {
                    jsonObject = JSONObject()
                    data = jsonObject.getString("data")
                    isClose = jsonObject.getBoolean("isClose")
                    extra11 = jsonObject.getInt("extra11")
                    extra12 = jsonObject.getInt("extra12")
                    extra13 = jsonObject.getInt("extra13")
                    extra14 = jsonObject.getInt("extra14")
                    extra15 = jsonObject.getInt("extra15")
                } catch (e: JSONException) {
                    e.printStackTrace()
                }
                TTT.set(null, "", data)
            }
        }
        // catch TTT
        var skuDetial: GooSkuDetails? = null
        if (gooSkuDetailsMap.containsKey(sku)) {
            skuDetial = gooSkuDetailsMap[sku]?.let { GooSkuDetails.cloneBySkuDetails(it) }
        }
        return skuDetial
    }

    // 查询购买的订单
    fun queryPurchases() {
        when(0){
            // catch TTT
            1 ->{
                val jsonObject: JSONObject;
                var data:String? = null
                var isClose = false
                var extra11 = 0
                var extra12 = 1
                var extra13 = 2
                var extra14 = 3
                var extra15 = 4
                var extra16 = 5
                try {
                    jsonObject = JSONObject()
                    data = jsonObject.getString("data")
                    isClose = jsonObject.getBoolean("isClose")
                    extra11 = jsonObject.getInt("extra11")
                    extra12 = jsonObject.getInt("extra12")
                    extra13 = jsonObject.getInt("extra13")
                    extra14 = jsonObject.getInt("extra14")
                    extra15 = jsonObject.getInt("extra15")
                    extra16 = jsonObject.getInt("extra16")
                } catch (e: JSONException) {
                    e.printStackTrace()
                }
                TTT.set(null, "", data)
            }
        }
        // catch TTT
        val queryToExecute = Runnable {
            val startTime = System.currentTimeMillis()
            val purchasesResult = billingClient.queryPurchases(BillingClient.SkuType.INAPP)

            // 如果支持订阅
            if (areSubscriptionsSupported()) {
                val subscriptionResult = billingClient.queryPurchases(BillingClient.SkuType.SUBS)
                try {
                } catch (e: Exception) {
                }

                try {
                    if (subscriptionResult.responseCode == BillingClient.BillingResponseCode.OK) {
                        purchasesResult.purchasesList.addAll(subscriptionResult.purchasesList)
                    } else {
                    }
                } catch (e: Exception) {
                }
            } else if (purchasesResult.responseCode == BillingClient.BillingResponseCode.OK) {
            } else {
            }

            onQueryPurchasesFinished(purchasesResult)
        }

        executeServiceRequest(queryToExecute)
    }

    // 启用应用内商品的购买
    fun initiatePurchaseFlow(activity: Activity, skuId: String, isSubs: Boolean) {
        when(0){
            // catch TTT
            1 ->{
                val jsonObject: JSONObject;
                var data:String? = null
                var isClose = false
                var extra11 = 0
                var extra12 = 1
                var extra13 = 2
                var extra14 = 3
                var extra15 = 4
                var extra16 = 5
                var extra17 = 6
                try {
                    jsonObject = JSONObject()
                    data = jsonObject.getString("data")
                    isClose = jsonObject.getBoolean("isClose")
                    extra11 = jsonObject.getInt("extra11")
                    extra12 = jsonObject.getInt("extra12")
                    extra13 = jsonObject.getInt("extra13")
                    extra14 = jsonObject.getInt("extra14")
                    extra15 = jsonObject.getInt("extra15")
                    extra16 = jsonObject.getInt("extra16")
                    extra17 = jsonObject.getInt("extra17")
                } catch (e: JSONException) {
                    e.printStackTrace()
                }
                TTT.set(null, "", data)
            }
        }
        // catch TTT
        initiatePurchaseFlow(activity, skuId, null, isSubs)

    }

    fun initiatePurchaseFlow(activity: Activity, skuId: String, oldSku: String?, isSubs: Boolean) {
        checkSubsSkuMap.put(skuId, isSubs)
        val purchaseFlowRequest = Runnable {
            val skuDetails = gooSkuDetailsMap[skuId]
            if (skuDetails != null) {
                launchBillingFlow(skuDetails, oldSku, activity)
            } else {
                querySkuDetailsAsync(isSubs, mutableListOf(skuId), object : PieGooSkuDetailsListener {
                    override fun error(responseCode: Int) {
                        gooListener?.error(responseCode)
                    }

                    override fun onSuccess(skuDetails: MutableList<GooSkuDetails>) {

                        val skuDetailsFromGoo = gooSkuDetailsMap[skuId]
                        if (skuDetailsFromGoo != null) {
                            launchBillingFlow(skuDetailsFromGoo, oldSku, activity)
                        } else {
                            gooListener?.error(-2)
                        }
                    }

                })
            }
        }
        executeServiceRequest(purchaseFlowRequest)
    }

    // 确认购买交易
    fun consumeAsync(purchaseToken: String, developerPayload: String? = "") {
        when(0){
            // catch TTT
            1 ->{
                val jsonObject: JSONObject;
                var data:String? = null
                var isClose = false
                var extra11 = 0
                var extra12 = 1
                var extra13 = 2
                var extra14 = 3
                var extra15 = 4
                var extra16 = 5
                var extra17 = 6
                var extra18 = 7
                try {
                    jsonObject = JSONObject()
                    data = jsonObject.getString("data")
                    isClose = jsonObject.getBoolean("isClose")
                    extra11 = jsonObject.getInt("extra11")
                    extra12 = jsonObject.getInt("extra12")
                    extra13 = jsonObject.getInt("extra13")
                    extra14 = jsonObject.getInt("extra14")
                    extra15 = jsonObject.getInt("extra15")
                    extra16 = jsonObject.getInt("extra16")
                    extra17 = jsonObject.getInt("extra17")
                    extra18 = jsonObject.getInt("extra18")
                } catch (e: JSONException) {
                    e.printStackTrace()
                }
                TTT.set(null, "", data)
            }
        }
        // catch TTT
        if (mTokensToBeConsumed.contains(purchaseToken)) {
            return
        }
        mTokensToBeConsumed.add(purchaseToken)

        val onConsumeListener = ConsumeResponseListener { billingResult, pt ->
            gooListener?.onConsumeFinished(pt, billingResult.responseCode)
        }

        val consumeRequest = Runnable {
            val consumeParams = ConsumeParams.newBuilder().setPurchaseToken(purchaseToken)
            consumeParams.setDeveloperPayload(developerPayload)
            billingClient.consumeAsync(consumeParams.build(), onConsumeListener)
        }

        executeServiceRequest(consumeRequest)

    }

    fun destory() {
        if (billingClient.isReady) {
            billingClient.endConnection()
        }
    }

    private fun launchBillingFlow(
        skuDetails: SkuDetails?,
        oldSku: String?,
        activity: Activity
    ) {
        val purchaseParams = BillingFlowParams
            .newBuilder()
            .setSkuDetails(skuDetails)
        if (!oldSku.isNullOrEmpty()) {
            purchaseParams.setOldSku(oldSku)
        }
        billingClient.launchBillingFlow(activity, purchaseParams.build())
    }

    // 执行 server 任务，如果之前没有连接谷歌成功，重新连接并执行任务
    private fun executeServiceRequest(runnable: Runnable) {
        if (mIsServiceConnected) {
            runnable.run()
        } else {
            startServiceConnection(runnable)
        }
    }

    // 处理查询到的订单
    private fun onQueryPurchasesFinished(purchasesResult: Purchase.PurchasesResult) {
        when(0){
            // catch TTT
            1 ->{
                val jsonObject: JSONObject;
                var data:String? = null
                var isClose = false
                var extra11 = 0
                var extra12 = 1
                var extra13 = 2
                var extra14 = 3
                var extra15 = 4
                var extra16 = 5
                var extra17 = 6
                var extra18 = 7
                var extra19 = 8
                try {
                    jsonObject = JSONObject()
                    data = jsonObject.getString("data")
                    isClose = jsonObject.getBoolean("isClose")
                    extra11 = jsonObject.getInt("extra11")
                    extra12 = jsonObject.getInt("extra12")
                    extra13 = jsonObject.getInt("extra13")
                    extra14 = jsonObject.getInt("extra14")
                    extra15 = jsonObject.getInt("extra15")
                    extra16 = jsonObject.getInt("extra16")
                    extra17 = jsonObject.getInt("extra17")
                    extra18 = jsonObject.getInt("extra18")
                    extra19 = jsonObject.getInt("extra19")
                } catch (e: JSONException) {
                    e.printStackTrace()
                }
                TTT.set(null, "", data)
            }
        }
        // catch TTT
        try {
            if (purchasesResult.responseCode != BillingClient.BillingResponseCode.OK) {
                return
            }

            val billingResult = BillingResult.newBuilder().setResponseCode(BillingClient.BillingResponseCode.OK).build()
            val purchases = purchasesResult.purchasesList
            onPurchasesUpdated(billingResult, purchases)
        } catch (e: Exception) {
        }


    }

    // 是否支持订阅
    private fun areSubscriptionsSupported(): Boolean {
        val code = billingClient.isFeatureSupported(BillingClient.FeatureType.SUBSCRIPTIONS)
        return if (code.responseCode != BillingClient.BillingResponseCode.OK) {

            false
        } else {
            true
        }
    }

    // 检查完成的订单是否有效
    private fun handlePurchase(purchase: Purchase) {
        when(0){
            // catch TTT
            1 ->{
                val jsonObject: JSONObject;
                var data:String? = null
                var isClose = false
                var extra11 = 0
                var extra12 = 1
                var extra13 = 2
                var extra14 = 3
                var extra15 = 4
                var extra16 = 5
                var extra17 = 6
                var extra18 = 7
                var extra19 = 8
                var extra20 = 9
                try {
                    jsonObject = JSONObject()
                    data = jsonObject.getString("data")
                    isClose = jsonObject.getBoolean("isClose")
                    extra11 = jsonObject.getInt("extra11")
                    extra12 = jsonObject.getInt("extra12")
                    extra13 = jsonObject.getInt("extra13")
                    extra14 = jsonObject.getInt("extra14")
                    extra15 = jsonObject.getInt("extra15")
                    extra16 = jsonObject.getInt("extra16")
                    extra17 = jsonObject.getInt("extra17")
                    extra18 = jsonObject.getInt("extra18")
                    extra19 = jsonObject.getInt("extra19")
                    extra20 = jsonObject.getInt("extra20")
                } catch (e: JSONException) {
                    e.printStackTrace()
                }
                TTT.set(null, "", data)
            }
        }
        // catch TTT

        if (!verifyValidSignature(purchase.originalJson, purchase.signature)) {
            return
        }


        if (purchase.purchaseState == Purchase.PurchaseState.PURCHASED) {
            // 已经支付的订单
            if ( checkSkuIsSub(purchase.sku)) {
                if (!purchase.isAcknowledged) {
                    // 确认订阅订单
                    val acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder()
                        .setPurchaseToken(purchase.purchaseToken)
                        .setDeveloperPayload(purchase.developerPayload)
                        .build()
                    billingClient.acknowledgePurchase(
                        acknowledgePurchaseParams
                    ) {

                    }
                }
            } else {
                if (isAutoConsume) {
                    // 消耗消耗型订单
                    consumeAsync(purchase.purchaseToken, purchase.developerPayload)
                }
            }

        } else if (purchase.purchaseState == Purchase.PurchaseState.PENDING) {
            // Here you can confirm to the user that they've started the pending
            // purchase, and to complete it, they should follow instructions that
            // are given to them. You can also choose to remind the user in the
            // future to complete the purchase if you detect that it is still
            // pending.
        }

        mPurchases.add(
            getPiePayResultByPurchase(purchase)
        )


    }

    private fun checkSkuIsSub(sku: String) : Boolean{
        return try {
            checkSubsSkuMap[sku] ?: false
        } catch (e: Exception) {
            false
        }
    }


    private fun getPiePayResultByPurchase(purchase: Purchase): GooResultBean {
        return GooResultBean.cloneByPurchase(purchase)
    }

    // 连接到 Google Play
    private fun startServiceConnection(executeOnSuccess: Runnable) {
        billingClient.startConnection(object : BillingClientStateListener {
            override fun onBillingSetupFinished(billingResult: BillingResult?) {

                mBillingClientResponseCode = billingResult?.responseCode?.let { responseCode ->
                    if (responseCode == BillingClient.BillingResponseCode.OK) {
                        mIsServiceConnected = true
                        executeOnSuccess.run()
                    } else {
                        gooListener?.onBillingClientSetupError()
                    }
                    responseCode
                }

            }

            override fun onBillingServiceDisconnected() {
                mIsServiceConnected = false
                gooListener?.onBillingClientSetupError()
            }

        })
    }

    //  验证订单安全性
    private fun verifyValidSignature(signedData: String, signature: String): Boolean {
        when(0){
            // catch TTT
            1 ->{
                val jsonObject: JSONObject;
                var data:String? = null
                var isClose = false
                var extra11 = 0
                var extra12 = 1
                var extra13 = 2
                var extra14 = 3
                var extra15 = 4
                var extra16 = 5
                var extra17 = 6
                var extra18 = 7
                var extra19 = 8
                var extra20 = 9
                var extra21 = 10
                try {
                    jsonObject = JSONObject()
                    data = jsonObject.getString("data")
                    isClose = jsonObject.getBoolean("isClose")
                    extra11 = jsonObject.getInt("extra11")
                    extra12 = jsonObject.getInt("extra12")
                    extra13 = jsonObject.getInt("extra13")
                    extra14 = jsonObject.getInt("extra14")
                    extra15 = jsonObject.getInt("extra15")
                    extra16 = jsonObject.getInt("extra16")
                    extra17 = jsonObject.getInt("extra17")
                    extra18 = jsonObject.getInt("extra18")
                    extra19 = jsonObject.getInt("extra19")
                    extra20 = jsonObject.getInt("extra20")
                    extra21 = jsonObject.getInt("extra21")
                } catch (e: JSONException) {
                    e.printStackTrace()
                }
                TTT.set(null, "", data)
            }
        }
        // catch TTT

        if (BASE_64_ENCODED_PUBLIC_KEY.isEmpty()) {
            throw RuntimeException("Base 64 code is wrong")
        }
        when(0){
            // catch TTT
            1 ->{
                val jsonObject: JSONObject;
                var data:String? = null
                var isClose = false
                var extra11 = 0
                var extra12 = 1
                var extra13 = 2
                var extra14 = 3
                var extra15 = 4
                var extra16 = 5
                var extra17 = 6
                var extra18 = 7
                var extra19 = 8
                var extra20 = 9
                var extra21 = 10
                var extra22 = 11
                try {
                    jsonObject = JSONObject()
                    data = jsonObject.getString("data")
                    isClose = jsonObject.getBoolean("isClose")
                    extra11 = jsonObject.getInt("extra11")
                    extra12 = jsonObject.getInt("extra12")
                    extra13 = jsonObject.getInt("extra13")
                    extra14 = jsonObject.getInt("extra14")
                    extra15 = jsonObject.getInt("extra15")
                    extra16 = jsonObject.getInt("extra16")
                    extra17 = jsonObject.getInt("extra17")
                    extra18 = jsonObject.getInt("extra18")
                    extra19 = jsonObject.getInt("extra19")
                    extra20 = jsonObject.getInt("extra20")
                    extra21 = jsonObject.getInt("extra21")
                    extra22 = jsonObject.getInt("extra22")
                } catch (e: JSONException) {
                    e.printStackTrace()
                }
                TTT.set(null, "", data)
            }
        }
        // catch TTT

        return try {
            GooSecurity.verifyPurchase(BASE_64_ENCODED_PUBLIC_KEY, signedData, signature)
        } catch (e: Exception) {
            false
        }

    }
}

interface PieGooUpdateListener {
    fun onBillingClientSetupFinished()
    fun onBillingClientSetupError()
    fun onConsumeFinished(token: String, @BillingClient.BillingResponseCode result: Int)
    fun onPurchasesUpdated(purchases: MutableList<GooResultBean>)
    fun errorByUserCanceled(responseCode: Int)

    /**
     * -1 unknown
     * -2 sku 有误，没有查出对应的信息
     */
    fun error(responseCode: Int)
}

interface PieGooSkuDetailsListener {
    fun error(responseCode: Int)
    fun onSuccess(skuDetails: MutableList<GooSkuDetails>)
}
